package kassiopeia.gui

import groovy.util.XmlParser;
import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipFile;
import org.apache.log4j.Logger;
import kassiopeia.commons.model.Coordinates;
import kassiopeia.commons.model.plugin.PluginDescriptor;
import kassiopeia.commons.model.xml.PluginDescriptorXmlSerializer;
import kassiopeia.gui.task.Connection;
import kassiopeia.gui.task.Parameter;
import kassiopeia.gui.task.Plugin;
import kassiopeia.gui.task.Task;

class CompositionController {

    private static final Logger log = Logger.getLogger(CompositionController.class)

    RepositoryService repositoryService
    TaskDatabaseService taskDatabaseService

    def index = {
        def task
        if(session.taskName) {
            task = taskDatabaseService.getTaskByName(session.taskName)
        } else {
            task = null
        }
        [tasks:taskDatabaseService.getAllTasks(),task:task]
    }

    def createTaskDialog = {
        render(template:"createTaskDialog")
    }

    def saveTask = {
        Task task = new Task(name:params.taskName, description:params.taskDescription)
        if(taskDatabaseService.saveTask(task)) {
            flash.message = "Task saved successfully"
            session.taskName = task.name
        } else {
            flash.message = "There already exists task with given name or invalid name"
        }
        redirect(action:index)
    }

    def deleteTask = {
        if(taskDatabaseService.deleteTaskByName(params.taskName)) {
            flash.message = "Task deleted successfully"
        } else {
            flash.message = "Invalid task name"
        }

        if(session.taskName?.equals(params.taskName)) {
            session.taskName = null
        }
        redirect(action:index)
    }

    def editTask = {
        session.taskName = params.taskName
        redirect(action:index)
    }

    /**
     * First part of 'Create Plugin' dialog. Show coordinates of all plugins in repository.
     */
    def choosePluginDialog = {
        render(template:"choosePluginDialog",model:[plugins:repositoryService.getAllCoordinates()])
    }

    /**
    * Second part of 'Create Plugin' dialog. Load form with plugin properties.
    */
   def setupPluginDialog = {
       def descriptor = repositoryService.getDescriptor(params.pluginId, params.groupId, params.version)
       render(template:"setupPluginDialog", model:[descriptor:descriptor])
   }

   /**
    * Action called when user clicks 'Save plugin' in 'Create Plugin' dialog.
    */
   def savePlugin = {
       if(taskDatabaseService.savePlugin(session.taskName,createPluginFromParams(params))) {
           flash.message = "Plugin saved successfully"
       } else {
           flash.message = "Invalid plugin"
       }
       redirect(action:index)
   }

   /**
    * Show plugin's properties when user clicks 'Show' button.
    */
   def pluginPropertiesDialog = {
       render(template:"pluginPropertiesDialog", model:[plugin:taskDatabaseService.getPluginById(session.taskName,params.instanceId)])
   }

    def deletePlugin = {
        if(taskDatabaseService.deletePlugin(session.taskName,params.instanceId)) {
            flash.message = "Plugin deleted successfully"
        } else {
            flash.message = "Invalid plugin"
        }
        redirect(action:index)
    }

    def saveConnection = {
        String[] parts = params.from.split("::")
        Connection connection = new Connection(fromInstanceId:parts[0],fromOutputId:parts[1],toInstanceId:params.to)

        if(taskDatabaseService.saveConnection(session.taskName,connection)) {
            flash.message = "Connection saved successfully"
        } else {
            flash.message = "Invalid connection"
        }
        redirect(action:index)
    }

    def createConnectionDialog = {
        def task = taskDatabaseService.getTaskByName(session.taskName)
        def model = [
            outputs:getOutputs(task),
            inputs:getInputs(task)
        ]
        render(template:"createConnectionDialog",model:model)
    }

    def deleteConnection = {
        String[] parts = params.connection.split("::")
        Connection connection = new Connection(fromInstanceId:parts[0],fromOutputId:parts[1],toInstanceId:parts[2])
        if(taskDatabaseService.deleteConnection(session.taskName,connection)) {
            flash.message = "Connection deleted successfully"
        } else {
            flash.message = "Invalid connection"
        }
        redirect(action:index)
    }

    private def createPluginFromParams(params) {
        Plugin plugin = new Plugin()
        plugin.instanceId = params.instanceId
        plugin.pluginId = params.pluginId
        plugin.groupId = params.groupId
        plugin.pluginVersion = params.version

        for(param in params) {
            if(param.key.startsWith("P")) {
                plugin.addToParameters(new Parameter(name:param.key.substring(1),value:param.value))
            }
        }
        return plugin
    }

    private def getOutputs(Task task) {
        def outputs = [:]
        task.plugins.each { plugin ->
            PluginDescriptor descriptor = repositoryService.getDescriptor(plugin.pluginId, plugin.groupId, plugin.pluginVersion)
            descriptor.outputDescriptors.each { output ->
				def key = plugin.instanceId + "::" + output.name
				def value = plugin.instanceId + "::" + output.id
				outputs[key] = value
            }
        }
        return outputs
    }

    private def getInputs(Task task) {
        def inputs = []
        task.plugins.each { plugin ->
            inputs.add(plugin.instanceId)
        }
        return inputs
    }
}
